/** @file
 * @brief TiROS Debugging Interface
 */

#ifndef __TIROS_DEBUG_H_
#define __TIROS_DEBUG_H_

/* Author: Ratish J. Punnoose, 2006
 * This file is part of TiROS, the Tickless Real-Time Operating System.
 * Copyright(c) 2006, 2007: Ratish J. Punnoose.
 * Copyright(c) 2006 Sandia Corporation. Under the terms of Contract
 * DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
 * certain rights in this software. 
 * 
 * TiROS is free software; you can redistribute it and/or modify it under
 * the terms of the GNU General Public License as published by the Free
 * Software Foundation; either version 2 or (at your option) any later version.
 *
 * TiROS is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * for more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with TiROS; if not, write to the Free Software Foundation, Inc.,
 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
 *
 * As a special exception, if other files instantiate templates or use macros
 * or inline functions from this file, or you compile this file and link it
 * with other works to produce a work based on this file, this file does not
 * by itself cause the resulting work to be covered by the GNU General Public
 * License. However the source code for this file must still be made available
 * in accordance with section (3) of the GNU General Public License.
 *
 * This exception does not invalidate any other reasons why a work based on
 * this file might be covered by the GNU General Public License.
 *
 */




/** @addtogroup os_advanced
 *
 *    @{ */


/** A representation of the debug header data.
 *
 * TiROS does not use this structure directly.  This is presented here
 * to illustrate the type of debug data that TiROS encodes. */
struct os_data_hdr {
	/** Byte 1: Options.  RegisterPassing, ExtraDebugging, 
	 * \verbatim
	     Reserved -      4 bit.
	     prio_sort_method - 2 bits  -- 00 - not included.
	                                   01 - method = 1
	                                   10 - method = 2
	                                   11 - method = 3
	     RegisterPassing - 1 bit.
	     StackChecking - 1 bit.
	  \endverbatim
	 */
	unsigned char os_options;

	/** Byte 2: Data Type sizes 1.
	 * Data type sizes are either 8,16,32,64 bits. Any value in
	 * between (for ex. 24 bits) is padded up to the next highest 
	 * value. 
	 *\verbatim
	  tid_t size  - 2 bits: 8, 16, 32, 64 bits.
	  subtime_t size - 2 bits: 8, 16, 32, 64 bits.
	  flag_t size    - 2 bits: 8, 16, 32, 64 bits. 
	  osword_t size - 2bits
	 \endverbatim */
	unsigned char data_sizes1;

	/** Byte 3: Data Type sizes 2. 
	  Pointer Word size   - 2 bits: 8, 16, 32, 64 bits */
	unsigned char data_sizes2; 


	unsigned char os_max_procs; /**< TIROS_MAX_PROCS */

	/* This structure will align nicely on a four byte boundary */	
};

/** \cond */

#define TIROS_DEBUG_PRIOSORT_SET(x)  ( (x&0x03) << 2)
#define TIROS_DEBUG_PRIOSORT_GET(x) ( (x >> 2) & 0x03)

#define TIROS_DEBUG_REG_PASSING	(0x01 << 1)
#define TIROS_DEBUG_STKCHK	(0x01 << 0)

#define TIROS_DEBUG_SETNUMBYTES(val, bitpos)  ( (val & 0x03) << bitpos)
#define TIROS_DEBUG_GETSZ(byte, bitpos)       ( 1 << ((byte >> bitpos) & 0x03))

#define osword_t_OFFSET      	0
#define tid_t_OFFSET        	6
#define subtime_t_OFFSET    	4
#define flag_t_OFFSET       	2
#define osptrword_t_OFFSET      0

/** \endcond */


#ifdef TIROSINT_DATA_DEBUG
#include "tr_int.h"
#include "tr_llmgr.h"


/* tr_int.h and tr_llmgr.h are included since they are also relevant
 * for debugging.  tr_int.h provides apis to get the state of kernel
 * data structures.   tr_llmgr.h does the same, but contains all the
 * list management specific data. 
 * tr_int.h provides   osint_gettrdata(trintdata_t *);
 * tr_llmgr.h provides osint_getlistdata(trlistdata_t *); 
 **/


/** This structure is a representation of the global debug data.
 * This structure is not used anywhere directly.  It is used here to
 * describe the order and nature of the collected debug data. */
struct os_data_global {
	uint32_t curr_time_units;        
	subtime_t curr_time_subunits;
	tid_t running_task;
	tid_t readylisthead;
	tid_t waitlisthead;
	tid_t isr_nesting;
	/* The above data will align nicely on a four byte boundary */

	osword_t ctxt_switch_cnt;
	/* This will still keep it aligned on a word boundary */
};



/** This structure is a representation of the variable internal data.
 * 
 *  This structure shows how TiROS packs the debugging data.
 * Note that TiROS does not uses this structure directly.  
 */
struct os_data_per_task {
	struct TCB task_TCB; /* Per task TCB */

	osptr_t task_pc; /* Program counter */

#ifdef TIROS_STK_CHECK	
	osword_t curr_stkusage;   /* Current stack occupancy */
	osword_t max_stkusage;    /* Maximum stack occupancy of the task at
				    * any time */
#endif


#if (TIROS_PRIO_SORT_METHOD == 1)
	/* The following data is not related to this task, but is the
	 * entry in the appropriate queue for this tid index. */
	tid_t readyQ_val;    /* Task that is in the readyQ at index x */
	tid_t waitQ_val;     /* Task that is in the waitQ at index x */
#else
#error "TIROS_PRIO_SOFT_METHOD has undefined debug information"

#endif
	
};



/** This structure describes the data returned by osint_snapshot.
 * Note however, that the data is not organized into this structure.
 * The way this data is packed into a data stream is dependent
 * on the compiler, processor architecture and the sizes of the data
 * types used. So TiROS dos not use this structure, rather osint_snapshot
 * packs the data efficiently into a byte stream.  */
struct os_internal_debug_data {
	struct os_data_hdr     hdr;
	struct os_data_global  globals;
	struct os_data_per_task per_task[TIROS_MAX_PROCS];
}; 





/** Recommended size of the buffer to hold the TiROS internal debug data*/
#define TIROS_DEBUG_DATA_SZ  (sizeof (struct os_internal_debug_data))

 
/** A snapshot of all the internal os data.
 *
 *  This can be used by a dedicated task to send out debugging info
 *  The data is packed into a tight architecture independent
 *  little-endian byte stream.  The type of data that is packed is
 *  illustrated in  os_internal_debug_data.
 *  To use this function, tr_debug.h should be included by
 *  the source file and TIROSINT_DATA_DEBUG should be defined in
 *  proj_config.h
 *
 * The TiROS state is written in a compact endian-neutral format. This can be parsed using the
 * tiros_parse program that is  included with the distribution.  This
 * form of debugging provides a wealth of information. Here is example 
 * output, parsed by tiros_parse, showing the debug data output by the
 * example in os_examples/os_debug_example. This output was obtained
 * from an msp430_gcc port.
 *
 * NOTE: The information about the debugging task itself may not be
 * fully accurate.  It will reflect the state of the task at the last
 * context switch.
\verbatim
--------------------------------------------------
os_options = 0x07,  data_sizes1 = 0x15, data_sizes2 = 0x01, max_procs = 8
Record size = 240
 TIROS Settings
PrioSort: 1      reg_passing: 1         stk_chk_info: 1          oswordt_sz: 2
tidtsz: 1        subtimet_sz: 2          flagt_sz: 2    osptrwordt_sz: 2
max_procs: 8 
gdata_len: 12    data_per_task_len: 28  task_tcb_len: 20         record_sz: 240
********************************************************************************
         5:41515        RUN:  1 RDY:  1 WT:  0  NESTING:  0     CTXT_CNT:   12
--------------------------------------------------------------------------------
TSK     CP      PRIO    EFF     FLAGS   MUTXS   TIMEOUT                 LK_PTR  EVTS    ...
0       0x1310    0       0     0x10      0              6:  640        0xffff  0x0000  ...
1       0x13aa    1       1     0x00      0              5:41483        0xffff  0x0000  ...
2       0x1442    2       2     0x10      0     4294967295:65535        0x1530  0x0001  ...
3       0x150e    3       3     0x00      0              0:    0        0xffff  0x0000  ...
4       0xffff    0       0     0x00      0              0:    0        0x0000  0x0000  ...
5       0xffff    0       0     0x00      0              0:    0        0x0000  0x0000  ...
6       0xffff    0       0     0x00      0              0:    0        0x0000  0x0000  ...
7       0xffff    0       0     0x00      0              0:    0        0x0000  0x0000  ...
----------------------------------------------------------------------
  ...    STK     STKSZ   PC      CUR_STK MAX_STK R/W Q   LK Q    
  ...    0x12b8     79   0x472a     35      36   0x02    0xff    
  ...    0x1356     79   0xffff      0      38   0x03    0xff    
  ...    0x13f4     79   0x472a     40      41   0xff    0xff    
  ...    0x1492     79   0x59ec     17      30   0xff    0xff    
  ...    0x0000      0   0xffff      0       0   0xff    0xff    
  ...    0x0000      0   0xffff      0       0   0xff    0xff    
  ...    0x0000      0   0xffff      0       0   0xff    0xff    
  ...    0x0000      0   0xffff      0       0   0xff    0xff    
----------------------------------------------------------------------
\endverbatim
As can be seen, there is a prolific amount of information:
<UL>
 <LI>the sizes of all the data types including task control block sizes. </LI>
 <LI> the TIROS_MAX_PROCS value that was configured into the program
during compilation.</LI>
 <LI> Time.
 <LI> The running task ID, task IDs of the heads of the ready queue
 and wait queue. 
 <LI> the ISR nesting level. </LI>
 <LI> number of context switches since reset. </LI>
 </UL>
On a per-task basis, the following information is available:
<UL>
 <LI> TSK: The task id. </LI>
 <LI> CP: The current context pointer. </LI>
 <LI> PRIO: The priority of the task. </LI>
 <LI> EFF: The effective priorityof the task. </LI>
 <LI> FLAGS: Internal flags used to mark the task's state. </LI>
 <LI> MUTXS: The number of mutexes held by the task. </LI>
 <LI> TIMEOUT: The wait or sleep timeout. </LI>
 <LI> LK_PTR: Pointer to a lock that the task is waiting on if
       any. </LI>
 <LI> EVTS: Event bitmask that the task is waiting on. </LI>
 <LI> STK: The base stack pointer provided during task
 initialization. (only if TIROS_STK_CHECK is defined).</LI>
 <LI> STKSZ: The stack size provided during task initialization. (only
 if TIROS_STK_CHECK is defined).</LI>
 <LI> PC: The program counter (or instruction pointer) is available if
 the hardware port supports this. </LI>
 <LI> CUR_STK: The current stack usage is provided if the hardware
 port supports this. </LI>
 <LI> MAX_STK: The maximum stack usage of the task (throughout its run
 so far) is provided if the hardware port supports this. </LI>
</UL>
The R/W Q and LK Q columns can be used to decipher the order of the
tasks in the read/wait list and lock list respectively. 

 *  
 * @param [in] memaddr   Memory address to copy the data structures. 
 *                       If this is set to 0, the return
 *                       value contains the size that the data
 *                       structures would occupy in bytes.
 *                       It is recommended that buffer be
 *                       TIROS_DEBUG_DATA_SZ long.
 * @param [in] memsz     Size of the memory location.
 * @return  If memaddr is set to 0 this returns the size
 *          of the data structures, else
 *          ERR_FAILED, if not enough memory.
 *          the actual length of the byte stream, if success.
 */
int osint_snapshot(unsigned char *buffer , unsigned int memsz);


/** @} */



#endif 



#endif /* TIROS_DEBUG_H */
